<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 一、同步和异步的区别
        // 1.同步：同一时间只能做一件事情，做完之后，才能做后续的事情
        // 同步的优点：依次执行，有序
        // 同步的缺点：效率低下
        // 2.异步：同一时间可以同时做多个事情
        // 异步的优点：效率高
        // 异步的缺点：在某些必须有先后顺序的情况，可能会造成错误

        // 二、进程和线程
        // 1.进程：计算机已经运行的程序，是操作系统管理程序的一种方式；
        // 一般来说，一个程序就是一个进程，也有程序是多进程的（浏览器一个窗口就是一个进程）
        // 2.线程：操作系统能够运行运算调度的最小单位，通常情况下，线程是被包含在进程中
        // 每个进程中至少包含一个线程

        // 浏览器是多进程，每一个窗口就是一个进程，每个进程里面是多线程
        // JavaScript就是一个单线程，因此js代码执行的时候，同一时间只能执行一行代码

        // 举例：工厂就是一个进程，每一个工厂有很多车间，每一个车间就是线程

        // 操作系统是如何实现让多个进程同时运行（敲代码、直播、浏览器）
        // 1.因为CPU的运算速度非常快，它可以快速的在多个进程之间迅速切换
        // 2.当我们每一个进程中的线程获取到时间片时，就可以快速的执行我们编写的代码
        // 3.对于用户来说，是感觉不到这种切换

        // 三、实现异步
        // 1.多线程
        // 2.单线程非阻塞式（js实现异步）：js是单线程的，要实现js代码的异步，还需要浏览器窗口中其他线程的辅助



        // 四、事件循环：是值js单线程执行代码，遇到异步操作，把计时等工作交给其他线程来执行，计时完毕之后，
        // 把回调函数放到事件队列中，之后通知js线程来执行事件队列里面的回调函数的循环过程

        // 1.事件队列（先进先出）：里面包含宏任务和微任务
        // （1）宏任务队列里面包含：计时器（setInterval和setTimeout）、Ajax、DOM事件、UI渲染
        // （2）微任务队列里面包含：Promise.then 和 Promise.catch
        // 2.事件队列执行规范：必须先清空微任务队列，之后再执行宏任务队列

        // console.log("开始");
        // setTimeout(function () {
        //     console.log("hello");
        //     setTimeout(function () {
        //         console.log("1");
        //         setTimeout(function () {
        //             console.log("2222");
        //             setTimeout(function () {
        //                 console.log("3135");
        //             }, 2000);
        //         }, 2000);
        //     }, 2000);
        // }, 2000);
        // for (let i = 0; i <= 100000; i++) {
        //     console.log(i);
        // }
        // console.log("结束");


        // 五、回调函数实现异步操作：回调地狱
        // setTimeout(function () {
        //     console.log("hello");
        //     setTimeout(function () {
        //         console.log("1");
        //         setTimeout(function () {
        //             console.log("2222");
        //             setTimeout(function () {
        //                 console.log("3135");
        //             }, 2000);
        //         }, 2000);
        //     }, 2000);
        // }, 2000);

        // 构造函数：
        // （1）功能：生成对象
        // （2）参数：和普通函数相同
        // （3）返回值：默认返回值是对象
        // （4）声明方式和普通函数相同
        // （5）调用构造函数：new 函数名（） =>实例化对象
        // （6）构造函数名称首字母大写

        // 六、使用构造函数Promise来实现异步
        // 语法：
        // let 变量=new Promise(function(resolve,reject){
        // 注意：resolve和reject是形参变量，一般都用这两个名字，表示两个函数

        // })

        // let pm=new Promise(function(resolve,reject){
        //     console.log(123);

        //     // 1.resolve函数主要触发then方法，用于后续代码的执行
        //     // 2.reject函数主要触发catch方法，用于接受抛出的异常或错误信息

        //     if(true){
        //         resolve("666","777");
        //     }else{
        //         reject("xxx");
        //     }

        // });
        // console.log(pm);
        // // then方法：由resolve函数触发
        // let a=pm.then(function(res,res2){
        //     // res是形参变量，主要用于接受resolve函数传过来的参数
        //     // 注意：参数只能传一个，后面的参数无效
        //     console.log(res,res2);//666 undefined
        //     console.log('已实现');//

        //     // return "hello";
        //     // 相当于：
        //     return new Promise(function(resolve,reject){
        //         resolve("hello");
        //     })
        // }).then(function(res){
        //     console.log(res);//hello

        // }).then(function(res){
        //     console.log(res);//undefined  上一个then方法的返回值promise对象中默认调用resolve函数，但是没有传参
        // })
        // // then方法的返回值是一个promise对象，并且该promise默认调用resolve函数
        // console.log(a);


        // catch方法：由reject函数触发
        // let b=pm.catch(function(rej){
        //     console.log(rej);
        //     console.log("已拒绝")
        // })
        // catch方法的返回值是一个promise对象，并且该promise默认调用resolve函数
        // console.log(b);


        // finally方法：表示最后执行，无论前面执行的是哪一个函数，都会执行该方法
        // let c=pm.finally(function(){
        //     console.log("最后")

        // })
        // finally方法的返回值是一个promise对象，并且该promise继承pm对象的状态和参数
        // console.log(c);

        // (一)Promise对象执行有三种状态：
        // 一旦确定某种状态就不可以再修改，确定状态是由resolve和reject函数的调用先后顺序决定的
        // （1）pending状态：待定状态 =>没有执行resolve或者reject函数
        // （2）fulfilled状态：已实现状态 =>执行resolve函数
        //  (3) rejected状态：已拒绝状态 =>执行reject函数


        // （二）Promise简写
        // console.log(Promise.prototype);
        // let pm=Promise.resolve("666");
        // let pm2=Promise.reject("错误");
        // 相当于
        // let pm=new Promise(function(resolve,reject){
        //     resolve("666");
        // })
        // pm.then(function(res){
        //     console.log(res);
        // })
        // pm.catch(function(rej){
        //     console.log(rej);
        // })

        // 七、使用Promise实现：每间隔2秒钟输出一个字符串
        // function test(content,time) {
        //     return new Promise(function (resolve, reject) {
        //         setTimeout(function () {
        //             resolve(content);
        //         }, time);
        //     })
        // }

        // let pm=test("开始",2000);
        // pm.then(function (res) {
        //     console.log(res);
        //     return test("111",3000);
        // }).then(function (res) {
        //     console.log(res);
        //     return test("222",4000);
        // }).then(function (res) {
        //     console.log(res);
        //     return test("333",5000);
        // }).then(function (res) {
        //     console.log(res);
        // })


        // 注意：Promise可以实现异步操作，但是代码量并没有比之前的回调函数减少，
        // 甚至可能更多，为了更好的实现，进一度产生了迭代器和生成器

        // 八、迭代器(Iterator)
        // 1.概念：迭代器本身是一个对象，它可以帮助我们去遍历其他数据类型
        // 2.特点：
        // （1）迭代器是一个对象，但是不是所有的对象都是迭代器
        // （2）对象要成为一个迭代器需要符合迭代器
        // （3）迭代器协议定义了产生一系列值的标准方法
        // （4）在js中这个方法就是next()方法
        // 3.next()方法：
        // （1）next()本质是一个没参数的函数，返回值是一个对象
        // （2）该对象如下：{value:123,done:false}
        //  (3)value属性表示遍历数据得到的值
        // (4)done属性表示是否可以继续遍历，false表示还可以继续向下遍历，true表示遍历结束

        // （一）数组是自带迭代器：
        // let arr=[3,12,6,7,45];
        // console.log(arr);

        // let it=arr[Symbol.iterator]();//得到迭代器对象
        // console.log(it);
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());


        // （二）对象没有迭代器
        // let obj={
        //     name:"小米",
        //     age:18,
        //     height:180
        // }
        // console.log(obj[Symbol.iterator]);//undefined

        // for-of:只能遍历带有迭代器的数据的值
        // console.log(Object.values(obj));// ['小米', 18, 180]
        // for(let i of Object.values(obj)){
        //     console.log(i);
        // }


        // （三）手动给对象添加迭代器
        // let obj={
        //     name:"小米",
        //     age:18,
        //     height:180,
        //     // 迭代器
        //     [Symbol.iterator]:function(){
        //         let index=0;//数组下标
        //         let arr=Object.values(obj);
        //         return {
        //             next:function(){
        //                 if(index==arr.length){
        //                     return {value:undefined,done:true}
        //                 }else{
        //                     return {value:arr[index++],done:false}

        //                 }
        //             }
        //         }
        //     }
        // }
        // console.log(obj);
        // let it=obj[Symbol.iterator]();//得到迭代器对象
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());

        // for(let i of obj){
        //     console.log(i);
        // }

        // （四）js中自带迭代器的数据
        // 1.数组
        // 2.映射
        // 3.集合
        // 4.字符串
        // 5.类型数组
        // 6.伪数组对象（arguements 和 DOM节点）

        // （五）js中对于迭代器的实际应用
        // 1.for-of
        // 2.扩展运算符（...）
        // 3.数组解构和对象解构  [a,b]=[b,a]
        // 4.创建集合时传参数：参数是可迭代数据都行
        // let s=new Set("hello");
        // console.log(s);



        // 九、生成器
        // 1.概念：生成器是一种特殊的函数，是ES6新增的一种控制函数执行和使用的方法
        // 2.作用：控制函数执行，灵活地控制函数什么时候暂停，什么时候执行
        // 3.生成器函数的特点：
        // （1）生成器函数和普通函数的声明方式相同，只是需要在function关键字后面加上*
        // （2）生成器函数的功能：控制函数执行
        // （3）生成器函数的参数：和普通函数相同
        // （4）生成器函数的返回值是一个对象，该对象是生成器对象；生成器对象就是一个特殊的迭代器对象
        // （5）生成器函数内部执行yield，就会暂停函数体内部代码执行
        // （6）迭代器对象调用next()方法，可以让函数继续执行，再次遇到yield，就会再次暂停执行，直到函数结束

        // function* test(x) {
        //     console.log(x);
        //     yield 123;
        //     console.log(1111);
        //     yield 456;
        //     console.log(2222);
        // }

        // let it = test("hello"); //得到迭代器对象
        // console.log(it);
        // setTimeout(function () {
        //     console.log(it.next()); //{value: 123, done: false}
        // },2000);
        // console.log(it.next());//{value: 123, done: false}
        // console.log(it.next());//{value: 456, done: false}
        // console.log(it.next());//{value: undefined, done: true}


        // 使用生成器完成：每间隔2秒钟输出一个字符串
        // function test(content, time) {
        //     return new Promise(function (resolve, reject) {
        //         setTimeout(function () {
        //             resolve(content);
        //         }, time);
        //     })
        // }

        // function* delay() {
        //     yield test("1111", 2000);
        //     yield test("2222", 2000);
        //     yield test("3333", 2000);
        // }

        // let it = delay(); //得到生成器函数delay的迭代器对象
        // it.next().value.then(function (res) {
        //     console.log(res); //1111
        //     it.next().value.then(function (res) {
        //         console.log(res); //2222
        //         it.next().value.then(function (res) {
        //             console.log(res); //3333
        //         })
        //     })
        // })

        // 实现异步编程=>回调函数=>promise=>（迭代器）生成器=>async和await

        // 十、async和await实现异步（本质依然是生成器实现异步，只是语法糖而已）
        // 优点：async和await用同步的写法，完成异步的操作
        // async函数：本质就是生成器函数，只是简化了外部执行器的写法，是一种语法糖
        // async函数的返回值直接就是promise对象
        // await关键字取代之前的yeild，在async函数中使用
        // async关键字取代之前的*，在声明函数的时候使用

        // 声明async函数函数
        // async function test(){
        //     return await "123";
        //     // 相当于
        //     // let x=await new Promise(function(resolve,reject){
        //     //     resolve("123");
        //     // });
        //     // return x;
        // }
        // let pm=test();//接受到函数的返回值，是一个promise对象
        // console.log(pm);
        // pm.then(function(res){
        //     console.log(res);//"123"
        // })


        // 使用async和await来实现：每间隔2秒输出一个字符串
        // function test(content, time) {
        //     return new Promise(function (resolve, reject) {
        //         setTimeout(function () {
        //             resolve(content);
        //         }, time);
        //     })
        // }

        // async function delay(){
        //     // 写法1：
        //     let a=await test("1111",2000);//
        //     // 写法2：
        //     // let a=await new Promise(function(resolve,reject){
        //     //     resolve("1111");
        //     // })
        //     // 写法3：
        //     // let a=await "1111";//变量a就会获取到传入promise对象中resolve函数里面的参数，因此a="1111"
        //     console.log(a);

        //     let b=await test("2222",2000);
        //     console.log(b);

        //     let c=await test("3333",2000);
        //     console.log(c);
        // }
        // let pm=delay();


        // 练习：判断输出顺序
        // const delay = async () => {
        //     console.log('first');//（1）
        //     let data = await new Promise((resolve, reject) => resolve("hello"));//data="hello"
        //     console.log('aa');//(5)
        //     console.log(data);//"hello" (6)
        //     let data2 = await new Promise((resolve) => {
        //         setTimeout(() => {
        //             resolve('Yes')
        //         }, 2000)
        //     });
        //     console.log(data2);//"yes" (7)
        //     return 'World';
        // }
        // let result = delay();
        // console.log(result);//(2)输出promise对象 resolve("world");
        // result.then(function (data) {
        //     console.log("data:", data);//"world" (8)
        // });
        // console.log(11);//(3)
        // console.log(22);//(4)

        // js中实现异步的方式：回调函数=>promise=>生成器函数=>async和await
        // 1.异步和同步的区别
        // 2.进程和线程
        // 3.事件循环
        // 4.事件队列：宏任务和微任务队列
        // 5.promise的用法
        // 6.迭代器
        // 7.生成器
        // 8.async和await
    </script>
</body>

</html>